﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ScheduleMaker.DB;
using ScheduleMaker.DB.CoreDAO;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Transform;
using NHibernate.Criterion;

namespace ScheduleMaker.DB
{
    public class AdapterAbstractDAO<X, Y> where Y : X
    {
        private AbstractDAO<Y> wrappedAbstractDAO;
        public AdapterAbstractDAO(AbstractDAO<Y> wrappedAbstractDAO)
        {
            this.wrappedAbstractDAO = wrappedAbstractDAO;
        }

        public void save(X entity)
        {
            Y castEntity = (Y)entity;
            if (wrappedAbstractDAO != null)
            {
                wrappedAbstractDAO.createTransaction();
                AbstractDAO<Y>.session.Save(castEntity);
                wrappedAbstractDAO.commitTransaction();
            }
            else
            {
                throw new NotInitializedException("wrapped AbstractDAO object is not initialized");
            }
        }

        public void delete(X entity)
        {
            Y castEntity = (Y)entity;
            if (wrappedAbstractDAO != null)
            {
                wrappedAbstractDAO.createTransaction();
                AbstractDAO<Y>.session.Delete(castEntity);
                wrappedAbstractDAO.commitTransaction();
            }
            else
            {
                throw new NotInitializedException("wrapped AbstractDAO object is not initialized");
            }
        }

        public void update(X entity)
        {
            Y castEntity = (Y)entity;
            if (wrappedAbstractDAO != null)
            {
                wrappedAbstractDAO.createTransaction();
                AbstractDAO<Y>.session.Update(castEntity);
                wrappedAbstractDAO.commitTransaction();
            }
            else
            {
                throw new NotInitializedException("wrapped AbstractDAO object is not initialized");
            }
        }

        public void saveOrUpdate(Object entity)
        {
            Y castEntity = (Y)entity;
            if (wrappedAbstractDAO != null)
            {
                wrappedAbstractDAO.createTransaction();
                AbstractDAO<Y>.session.SaveOrUpdate(castEntity);
                wrappedAbstractDAO.commitTransaction();
            }
            else
            {
                throw new NotInitializedException("wrapped AbstractDAO object is not initialized");
            }
        }

        public X getById(int id)
        {
            Y entity;
            if(wrappedAbstractDAO != null)
            {
                wrappedAbstractDAO.createSession();
                entity = AbstractDAO<Y>.session.Get<Y>(id);
            }
            else
            {
                throw new NotInitializedException("wrapped AbstractDAO object is not initialized");
            }
            return (X)entity;
        }

        public IList<X> getAll()
        {
            List<Y> records;
            if(wrappedAbstractDAO != null)
            {
                wrappedAbstractDAO.createSession();
                ICriteria criteria = AbstractDAO<Y>.session.CreateCriteria(typeof(Y)).SetResultTransformer(new DistinctRootEntityResultTransformer()).AddOrder(Order.Asc("id"));
                records = (List<Y>)criteria.List<Y>();
            }
            else
            {
                throw new NotInitializedException("wrapped AbstractDAO object is not initialized");
            }
            return records.ConvertAll(record => (X)record);
        }


    }
}
